<script setup lang="ts">
import {ref, computed, type Ref} from 'vue';
import {type Ripple} from '@/types/ripple';
defineProps({
    type: {
        type: String,
        default: 'primary',
        validator: (value: string) => {
            return ['default', 'primary', 'secondary', 'success', 'warning', 'error', 'info'].includes(value);
        }
    },
    plain: {
        type: Boolean,
        default: false
    },
    disabled: {
        type: Boolean,
        default: false
    },
    loading: {
        type: Boolean,
        default: false
    }
});
// 按钮
const buttonEl: Ref<HTMLElement|null> = ref(null);
const ripples: Ref<Array<Ripple>> = ref([]);
let defaultRippleId = 0;
// 计算按钮位置
const buttonRect = computed(() => {
    return buttonEl.value?.getBoundingClientRect() || { left: 0, top: 0 };
});
// 动画时长计算（根据容器大小）
const getRippleDuration = () => {
    const size = Math.max(
        buttonEl.value?.offsetWidth || 0,
        buttonEl.value?.offsetHeight || 0
    );
    return Math.min(800, 100 + size * 2);
};
// 创建涟漪节点
const createRipple = (e: TouchEvent|MouseEvent): Ripple => {
    const {clientX, clientY} = (e as TouchEvent)?.touches?.[0] || e;
    const { left, top } = buttonRect.value;
    return {
        id: defaultRippleId++,
        style: {
            'left': `${clientX - left}px`,
            'top': `${clientY - top}px`,
            'animation-duration': `${getRippleDuration()}ms`
        }
    };
};
const onMouseDown = (e: TouchEvent|MouseEvent) => {
    ripples.value.push(createRipple(e));
};
const onMouseUp = () => {
    if (ripples.value.length > 0) {
        setTimeout(() => {
            ripples.value = ripples.value.slice(1);
        }, 400); // 需要与 CSS 动画时长匹配
    }
};
</script>

<template>
	<button
		ref="buttonEl"
		v-bind="$attrs"
		:class="[
			'nd-button',
			`nd-button--${type}`,
			plain ? 'is-plain' : '',
			disabled ? 'is-disabled' : '',
			loading ? 'is-loading' : ''
		]"
		:disabled="disabled"
		@mousedown="!disabled && onMouseDown($event)"
		@mouseup="!disabled && onMouseUp()"
	>
		<span
			v-if="loading"
			class="nd-button-loading-icon"
		/>
		<span
			class="nd-button-content"
			:class="{ 'is-loading': loading }"
		>
			<slot />
		</span>
		<transition-group>
			<span
				v-for="ripple in ripples"
				:key="ripple?.id"
				class="nd-ripple-effect"
				:style="ripple?.style"
			/>
		</transition-group>
	</button>
</template>
<style lang="scss">
@import '@/assets/scss/modules/nd-button.scss';
</style>